package cn.agiledata.bank.linkbank.impl.cmb;

import java.math.BigDecimal;
import java.util.Date;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import cn.agiledata.bank.common.util.DateUtil;
import cn.agiledata.bank.linkbank.exception.LinkBankException;
import cn.agiledata.bank.linkbank.impl.AbstractBankPayRequest;
import cn.agiledata.bank.linkbank.impl.AbstractBankTelPayRequest;

/**
 * 招商银行电话银行支付请求
 * 
 * @author 马贤波
 * 
 */
public class CmbTelPayRequest extends AbstractBankTelPayRequest {

    public CmbTelPayRequest() {
        super();
        init();
    }

    private void init() {
        setParameter(CmbTelConstant.COMMAND_TYPE,
                CmbTelConstant.COMMAND_TYPE_CREATE); // 操作类型：生成订单
        setParameter(CmbTelConstant.NOTIFY, CmbTelConstant.NOTIFY_YES); // 通知标志：通知
        setParameter(CmbTelConstant.MERCHANT_PARAMETER, ""); // 商户参数
        setParameter(CmbTelConstant.MERCHANT_EXTEND, ""); // 商户扩展信息
        setOrderKey("");
        setParameter(CmbTelConstant.BUYER_EXTEND, ""); // 买家扩展信息
        setParameter(CmbTelConstant.ORDER_CURRENCY_TYPE,
                CmbTelConstant.ORDER_CURRENCY_TYPE_CNY); // 货币类型：人民币
        setParameter(CmbTelConstant.ORDER_DESCRIPTION, ""); // 订单描述
        setParameter(CmbTelConstant.ORDER_EXTEND, ""); // 订单扩展信息
    }

    protected AbstractBankPayRequest getCopiedInstance() {
        return new CmbTelPayRequest();
    }

    public void setMerchantId(String merchantId) {
        setParameter(CmbTelConstant.MERCHANT_ID, merchantId);
    }

    public void setMerchantName(String merchantName) {
        setParameter(CmbTelConstant.MERCHANT_NAME, merchantName);
    }

    public void setBranchId(String branchId) {
        setParameter(CmbTelConstant.BRANCH_ID, branchId);
    }

    public String getMerchantUrl() {
        return getParameter(CmbTelConstant.MERCHANT_URL);
    }

    public void setMerchantUrl(String merchantUrl) {
        setParameter(CmbTelConstant.MERCHANT_URL, merchantUrl);
    }

    public void setOrderTelephone(String orderTelephone) {
        setParameter(CmbTelConstant.BUYER_TELEPHONE, orderTelephone);
    }

    /**
     * 
     * @param orderKey
     *            订单秘密数
     */
    public void setOrderKey(String orderKey) {
        setParameter(CmbTelConstant.BUYER_ORDER_KEY, orderKey);
    }

    public void setAmount(BigDecimal amount) {
        setParameter(CmbTelConstant.ORDER_AMOUNT, amount.setScale(2).toString());
    }

    public void setDate(Date date) {
        String dateValue = DateUtil.date2String(date,
                CmbTelConstant.ORDER_DATE_FORMAT);
        setParameter(CmbTelConstant.ORDER_TRANS_TIME, dateValue);
    }

    public void setExpireDate(Date expireDate) {
        String dateValue = DateUtil.date2String(expireDate,
                CmbTelConstant.ORDER_DATE_FORMAT);
        setParameter(CmbTelConstant.ORDER_EXPIRE_TIME, dateValue);
    }

    public void setOrderId(String orderId) {
        // 将交易编号作为商户参数发送给招商银行
        setParameter(CmbTelConstant.MERCHANT_PARAMETER, orderId);
        // 生成招商银行要求的格式的订单编号
        orderId = new CmbOrderIdTransformer(null).transId2OrderId(orderId);
        setParameter(CmbTelConstant.ORDER_ID, orderId);
    }

    private void addLeafTextElement(Element element, String fieldName) {
        String fieldValue = getParameter(fieldName);
        if (fieldValue == null) {
            fieldValue = "";
        }
        element.addElement(fieldName).setText(fieldValue);
    }

    private void addLeafTextElements(Element element, String[] fieldNames) {
        for (int i = 0; i < fieldNames.length; i++) {
            addLeafTextElement(element, fieldNames[i]);
        }
    }

    private void addCommandTypeElement(Element root) {
        addLeafTextElement(root, CmbTelConstant.COMMAND_TYPE);
    }

    private void addMerchantElement(Element root) {
        Element merchant = root.addElement(CmbTelConstant.MERCHANT);
        String[] fieldNames = { CmbTelConstant.MERCHANT_ID,
                CmbTelConstant.MERCHANT_NAME, CmbTelConstant.BRANCH_ID,
                CmbTelConstant.NOTIFY, CmbTelConstant.MERCHANT_URL,
                CmbTelConstant.MERCHANT_PARAMETER,
                CmbTelConstant.MERCHANT_EXTEND };
        addLeafTextElements(merchant, fieldNames);
    }

    private void addBuyerElement(Element root) {
        Element buyer = root.addElement(CmbTelConstant.BUYER);
        String[] fieldNames = { CmbTelConstant.BUYER_TELEPHONE,
                CmbTelConstant.BUYER_ORDER_KEY, CmbTelConstant.BUYER_EXTEND };
        addLeafTextElements(buyer, fieldNames);
    }

    private void addOrderElement(Element root) {
        Element order = root.addElement(CmbTelConstant.ORDER);
        String[] fieldNames = { CmbTelConstant.ORDER_ID,
                CmbTelConstant.ORDER_AMOUNT,
                CmbTelConstant.ORDER_CURRENCY_TYPE,
                CmbTelConstant.ORDER_TRANS_TIME,
                CmbTelConstant.ORDER_EXPIRE_TIME,
                CmbTelConstant.ORDER_DESCRIPTION, CmbTelConstant.ORDER_EXTEND };
        addLeafTextElements(order, fieldNames);
    }

    private String generatePayData() {
        Document doc = DocumentHelper.createDocument();
        Element root = doc.addElement(CmbTelConstant.PAY_DATA);
        addCommandTypeElement(root);
        addMerchantElement(root);
        addBuyerElement(root);
        addOrderElement(root);
        String xml = doc.asXML();
        xml = xml.replaceFirst("encoding=\"[Uu][Tt][Ff]-8\"",
                "encoding=\"gb2312\"");
        xml = xml.replaceFirst("\r?\n", "");
        return xml;
    }

    public void prepare() throws LinkBankException {
        setParameter(CmbTelConstant.PAY_DATA, generatePayData());
    }

    protected String[] getValidKeys() {
        return new String[] { CmbTelConstant.PAY_DATA };
    }
}